home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Programmer Power Tools
/
Programmer Power Tools.iso
/
asm
/
bmac.arc
/
BMAC.MAC
next >
Wrap
Text File
|
1988-07-27
|
8KB
|
245 lines
; bmac.mac 27 Oct 83 Craig Milo Rogers at USC/ISI
; Added BEXTRN to declare external routines.
; bmac.mac 27 Oct 83 Craig Milo Rogers at USC/ISI
; Added NOSAVE and PRIVATE parameters to the BENTRY macro.
; bmac.mac 17 Oct 83 Craig Milo Rogers at USC/ISI
; This version is designed to interface with the Lattice C
; environment. For example, subroutine agruments are stored with
; the first argument occupying the lowest address on the stack.
; The BP register is not handled quite correctly, however, so there
; may be incompatibilities with C library routines which expect a
; varying number of arguments.
;
; BMAC - Macros for 8088 Assembly Language
; Ron Burk, June 1983
; Dr. Dobbs Journal, Number 84, October 1983, pp. 98-106.
;
; Stack format (lowest address at bottom):
;
; | Previous data | <=== BP on call from C routines.
; +-----------------------+
; | Last Arg |
; | . |
; | . |
; | First Arg |
; +-----------------------+
; | (Optional Saved CS) |
; | Saved IP | <=== SP at start of BENTRY macro.
; +-----------------------+
; | Prev BP | <=== SP and BP after BENTRY macro.
; +-----------------------+
; | First Local |
; | . |
; | . |
; | Last Local | <=== SP after AUTO macro.
; +-----------------------+
; | First Reg |
; | . |
; | . |
; | Last Reg | <=== SP after SAVE macro.
; +-----------------------+
;
@ARGDEF MACRO ARGNAMES ;; Internal macro for defining args.
ifnb <ARGNAMES> ;; If there were any arguments:
if @nosave ;; Is BP being left untouched?
@err <No arguments allowed in BENTRY when NOSAVE is specified.>
endif
if LPROG ;; Large program model:
@nargs=4 ;; Allow 4 bytes for return address.
else ;; Small program model:
@nargs=2 ;; Allow 2 bytes for return address.
endif
irp arg,<ARGNAMES> ;; For each argument:
@nargs=@nargs+2 ;; Point to argument (skip saved BP).
arg&&@=@nargs ;; Define a redefinable offset.
ifndef arg ;; If name not yet defined:
arg equ [BP + arg&&@] ;; Define name itself.
endif
endm
endif
ENDM ;; End of @ARGDEF macro.
@ERR MACRO MSG ;; Print error message if in pass 1.
if1
%out MSG
endif
ENDM ;; End of @ERR macro.
@CHECK MACRO EXTRA,MACNAME ;; Checks for bad invocation.
ifnb <EXTRA>
@err <You forgot angle brackets in MACNAME macro.>
endif
ENDM ;; End of @CHECK macro.
BEXTRN MACRO FUNCS,MISTAKE ;; Declare external procedures:
ifb <FUNCS> ;; Check for missing argument.
@err <Missing function names on BEXTRN macro.>
endif
@check MISTAKE,BEXTRN ;; Check for missing brackets.
if LPROG ;; Large or small programs?
;; Large model:
irp func,<FUNCS> ;; Process list of functions.
EXTRN func:FAR ;; Declare an external routine.
endm
else
;; Small model:
PSEG ;; Programs are in this public segment.
irp func,<FUNCS> ;; Process list of functions.
EXTRN func:NEAR ;; Declare an external routine.
endm
ENDPS ;; Return to former segment.
endif
ENDM
BENTRY MACRO FUNC,ARGNAMES,OPTIONAL,MISTAKE ;; Defines procedure:
ifb <FUNC> ;; Check for missing function name.
@err <Missing function name on BENTRY macro.>
endif
@check MISTAKE,BENTRY ;; Check for missing brackets.
@nlv=0 ;; Number of bytes of local variables so far.
@savefl=0 ;; Set nonzero when SAVE macro has been used.
@nosave=0 ;; Set nonzero when BP is not to be saved.
@private=0 ;; Set nonzere when FUNC is not global.
irp flag,<@AX,@BX,@CX,@DX,@SI,@DI,@DS,@SS,@ES,@flags>
flag=0 ;; Initialize register flags.
endm
ifnb <OPTIONAL> ;; Any optional arguments?
irp keyword,<OPTIONAL> ;; Process list of optional keywords.
ifidn <keyword>,<NOSAVE> ;; Request to not save BP?
@nosave=1 ;; Yes, do not save BP.
else
ifidn <keyword>,<PRIVATE>
@private=1 ;; This is a local function.
else
@err <Unrecognized key word KEYWORD in BENTRY FUNC.>
endif
endif
endm
endif
@argdef <ARGNAMES> ;; Define argument offsets.
ife @private ;; Is this a global function?
PUBLIC FUNC ;; Publicly available procedure.
endif
if LPROG
FUNC PROC FAR ;; Long procedure pointers.
else
FUNC PROC NEAR ;; Short procedure pointers.
endif
ife @nosave ;; Don't save BP when NOSAVE is present.
PUSH BP ;; Save previous BP.
MOV BP,SP ;; Save pointer to arguments.
endif
ENDM ;; End of BENTRY macro.
AUTO MACRO VARS,MISTAKE ;; Defines local variables.
if @savefl ;; Must not use save before auto!
@err <***ERROR*** Must not SAVE before AUTO.>
endif
if @nosave ;; Does BP point to current stack loc?
@err <No auto variables allowed when NOSAVE is specified.>
endif
@check MISTAKE,AUTO ;; Check for missing brackets.
irp var,<VARS>
@nlv=@nlv+2 ;; Two more bytes of local variable.
var&&@=-@nlv ;; Offset of variable (skip saved BP).
ifndef var ;; If not defined,
var equ [BP + var&&@] ;; build permanent definition.
endif
endm
SUB SP,@nlv ;; Bump SP past local vars.
ENDM ;; End of AUTO macro.
@POP MACRO REG ;; Internal macro to pop a register.
if @® ;; If we saved this reg:
ifidn <reg>,<flags>
POPF ;; Use special instruction for flags.
else
POP REG ;; Use ordinary pop.
endif
endif
ENDM ;; End of @POP macro.
BEND MACRO FUNC ;; Define end of procedure.
ifb <FUNC>
@err <Missing name on BEND macro.>
endif
irp reg,<flags,ES,SS,DS,DI,SI,DX,CX,BX,AX>
@pop reg ;; Restore any saved registers.
endm
if @nlv ;; If any local variables,
ADD SP,@nlv ;; release stack space.
endif
ife @nosave ;; Don't restore BP if we didn't save it.
POP BP ;; Restore old BP.
endif
RET ;; Return to caller.
FUNC ENDP ;; Define end of procedure.
ENDM ;; End of BEND macro.
@SAVE MACRO R1,R2 ;; Famulus of SAVE macro.
ifidn <R1>,<R2> ;; If they are the same:
@&R1=1 ;; Set flag to show register saved.
@found=1 ;; Tell caller we found it.
endif
ENDM ;; End of @SAVE macro.
SAVE MACRO REGS,MISTAKE ;; Macro for saving registers.
if @savefl
@err <***ERROR*** Must not SAVE more than once.>
endif
@savefl=1 ;; Enforce ordering constraints.
@check MISTAKE,SAVE ;; Check for missing brackets.
irp reg,<REGS> ;; Check if all registers are known:
@found=0 ;; Haven't found register yet.
irp regname,<AX,BX,CX,DX,SI,DI,DS,SS,ES,flags>
@save regname,reg ;; Set corresponding register flag.
endm
ife @found ;; If we don't know a register:
@err <***ERROR*** 'reg': Unknown register name in SAVE.>
endif
endm
irp reg,<AX,BX,CX,DX,SI,DI,DS,SS,ES,flags>
if @&® ;; Are we supposed to save this register?
ifidn <flags>,<reg>
PUSHF ;; Special instruction to save flags.
else
PUSH reg ;; Save the register.
endif
endif
endm
ENDM ;; End of SAVE macro.
BCALL MACRO FUNC,ARGS,MISTAKE ;; Macro for calling procedures.
@check MISTAKE,FUNC ;; Check for missing brackets.
@nrgs=0 ;; Will get number of arguments.
ifnb <ARGS> ;; Any arguments to process?
irp arg,<ARGS>
@nrgs=@nrgs+1 ;; Count number of arguments.
endm
endif
@thsrg=@nrgs ;; Scan through all arguments,
rept @nrgs ;; right-to-left:
@i=@thsrg ;; Next, scan through arguments
irp arg,<ARGS> ;; left-to-right:
@i=@i-1 ;; Have we finally reached the
ife @i ;; desired argument?
PUSH arg ;; Yes, store it on the stack.
endif
endm ;; End of left-to-right scan.
@thsrg=@thsrg-1 ;; Set to look for previous argument.
endm ;; End of right-to-left scan.
CALL FUNC ;; Call the target procedure.
if @nrgs ;; Were there any arguments?
ADD SP,@nrgs*2 ;; Remove any arguments from stack.
endif
ENDM ;; End of BCALL macro.